# -*- coding: utf-8 -*-
"""
HTTP文件服务器插件
提供文件上传和下载功能
"""

import sys
import os
import threading
import socket
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.parse
import shutil
import mimetypes
import json
from datetime import datetime

# 添加父目录到路径，以便导入core模块
sys.path.append(os.path.dirname(os.path.dirname(__file__)))

from core.plugin_manager import BasePlugin


class FileServerHandler(BaseHTTPRequestHandler):
    """文件服务器处理器"""
    
    def __init__(self, *args, upload_dir=None, **kwargs):
        self.upload_dir = upload_dir or "uploads"
        super().__init__(*args, **kwargs)
    
    def do_GET(self):
        """处理GET请求 - 文件下载和页面显示"""
        if self.path == '/':
            self.send_upload_page()
        elif self.path == '/list':
            self.send_file_list()
        elif self.path.startswith('/download/'):
            self.handle_download()
        else:
            self.send_error(404, "File not found")
    
    def do_POST(self):
        """处理POST请求 - 文件上传"""
        if self.path == '/upload':
            self.handle_upload()
        else:
            self.send_error(404, "Not found")
    
    def send_upload_page(self):
        """发送文件上传页面"""
        html = """
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>文件上传服务器</title>
            <style>
                body { font-family: Arial, sans-serif; margin: 40px; }
                .upload-area { 
                    border: 2px dashed #ccc; 
                    border-radius: 10px; 
                    padding: 40px; 
                    text-align: center; 
                    margin: 20px 0;
                    background-color: #f9f9f9;
                }
                .upload-area:hover { border-color: #999; }
                .file-list { margin-top: 30px; }
                .file-item { 
                    padding: 10px; 
                    border-bottom: 1px solid #eee; 
                    display: flex; 
                    justify-content: space-between; 
                    align-items: center;
                }
                .download-btn { 
                    background: #007cba; 
                    color: white; 
                    padding: 5px 15px; 
                    text-decoration: none; 
                    border-radius: 3px; 
                }
                .download-btn:hover { background: #005a87; }
            </style>
        </head>
        <body>
            <h1>文件上传服务器</h1>
            <div class="upload-area" id="uploadArea">
                <p>拖拽文件到此处或点击选择文件</p>
                <input type="file" id="fileInput" multiple style="display: none;">
                <button onclick="document.getElementById('fileInput').click()">选择文件</button>
            </div>
            
            <div id="uploadStatus"></div>
            
            <div class="file-list">
                <h2>已上传的文件</h2>
                <div id="fileList">加载中...</div>
                <button onclick="loadFileList()">刷新列表</button>
            </div>

            <script>
                const uploadArea = document.getElementById('uploadArea');
                const fileInput = document.getElementById('fileInput');
                const uploadStatus = document.getElementById('uploadStatus');

                // 拖拽上传
                uploadArea.addEventListener('dragover', (e) => {
                    e.preventDefault();
                    uploadArea.style.backgroundColor = '#e6f3ff';
                });

                uploadArea.addEventListener('dragleave', (e) => {
                    e.preventDefault();
                    uploadArea.style.backgroundColor = '#f9f9f9';
                });

                uploadArea.addEventListener('drop', (e) => {
                    e.preventDefault();
                    uploadArea.style.backgroundColor = '#f9f9f9';
                    const files = e.dataTransfer.files;
                    uploadFiles(files);
                });

                // 文件选择上传
                fileInput.addEventListener('change', (e) => {
                    uploadFiles(e.target.files);
                });

                function uploadFiles(files) {
                    for (let file of files) {
                        uploadFile(file);
                    }
                }

                function uploadFile(file) {
                    const formData = new FormData();
                    formData.append('file', file);

                    uploadStatus.innerHTML = `<p>正在上传: ${file.name}</p>`;

                    fetch('/upload', {
                        method: 'POST',
                        body: formData
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.success) {
                            uploadStatus.innerHTML = `<p style="color: green;">上传成功: ${file.name}</p>`;
                            loadFileList();
                        } else {
                            uploadStatus.innerHTML = `<p style="color: red;">上传失败: ${data.error}</p>`;
                        }
                    })
                    .catch(error => {
                        uploadStatus.innerHTML = `<p style="color: red;">上传错误: ${error}</p>`;
                    });
                }

                function loadFileList() {
                    fetch('/list')
                    .then(response => response.json())
                    .then(files => {
                        const fileList = document.getElementById('fileList');
                        if (files.length === 0) {
                            fileList.innerHTML = '<p>暂无文件</p>';
                        } else {
                            fileList.innerHTML = files.map(file => 
                                `<div class="file-item">
                                    <span>${file.name} (${file.size})</span>
                                    <a href="/download/${encodeURIComponent(file.name)}" class="download-btn">下载</a>
                                </div>`
                            ).join('');
                        }
                    });
                }

                // 页面加载时获取文件列表
                loadFileList();
            </script>
        </body>
        </html>
        """
        
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.end_headers()
        self.wfile.write(html.encode('utf-8'))
    
    def handle_upload(self):
        """处理文件上传"""
        try:
            # 确保上传目录存在
            os.makedirs(self.upload_dir, exist_ok=True)
            
            content_type = self.headers['content-type']
            if not content_type.startswith('multipart/form-data'):
                self.send_json_response({'success': False, 'error': '无效的内容类型'})
                return
            
            # 解析multipart数据
            content_length = int(self.headers['Content-Length'])
            post_data = self.rfile.read(content_length)
            
            # 简单的multipart解析
            boundary = content_type.split('boundary=')[1].encode()
            parts = post_data.split(b'--' + boundary)
            
            for part in parts:
                if b'filename=' in part:
                    # 提取文件名
                    lines = part.split(b'\r\n')
                    for line in lines:
                        if b'filename=' in line:
                            filename = line.decode().split('filename="')[1].split('"')[0]
                            break
                    
                    # 提取文件内容
                    file_data_start = part.find(b'\r\n\r\n') + 4
                    file_data = part[file_data_start:-2]  # 移除结尾的\r\n
                    
                    if filename and file_data:
                        # 保存文件
                        file_path = os.path.join(self.upload_dir, filename)
                        with open(file_path, 'wb') as f:
                            f.write(file_data)
                        
                        self.send_json_response({
                            'success': True, 
                            'filename': filename,
                            'size': len(file_data)
                        })
                        return
            
            self.send_json_response({'success': False, 'error': '未找到文件数据'})
            
        except Exception as e:
            self.send_json_response({'success': False, 'error': str(e)})
    
    def handle_download(self):
        """处理文件下载"""
        try:
            # 移除 '/download/' 前缀并解码URL
            filename = urllib.parse.unquote(self.path[10:])
            print(f"[DEBUG] 请求下载文件: {filename}")
            
            # 构建完整文件路径
            file_path = os.path.join(self.upload_dir, filename)
            file_path = os.path.abspath(file_path)  # 获取绝对路径
            print(f"[DEBUG] 文件路径: {file_path}")
            print(f"[DEBUG] 文件是否存在: {os.path.exists(file_path)}")
            
            if not os.path.exists(file_path):
                print(f"[ERROR] 文件不存在: {file_path}")
                self.send_error(404, f"File not found: {filename}")
                return
            
            # 安全检查：确保文件在上传目录内
            upload_dir_abs = os.path.abspath(self.upload_dir)
            if not file_path.startswith(upload_dir_abs):
                print(f"[ERROR] 安全检查失败，文件不在上传目录内")
                self.send_error(403, "Access denied")
                return
            
            # 获取文件MIME类型
            mime_type, _ = mimetypes.guess_type(file_path)
            if mime_type is None:
                mime_type = 'application/octet-stream'
            
            file_size = os.path.getsize(file_path)
            print(f"[DEBUG] 开始发送文件，大小: {file_size} 字节")
            
            # 发送文件
            self.send_response(200)
            self.send_header('Content-type', mime_type)
            self.send_header('Content-Disposition', f'attachment; filename="{filename}"')
            self.send_header('Content-Length', str(file_size))
            self.end_headers()
            
            with open(file_path, 'rb') as f:
                try:
                    shutil.copyfileobj(f, self.wfile)
                    print(f"[DEBUG] 文件发送完成: {filename}")
                except (ConnectionAbortedError, BrokenPipeError) as e:
                    # 客户端提前断开连接，这是正常情况（比如下载完成）
                    print(f"[INFO] 客户端断开连接: {filename}")
                    return
                
        except Exception as e:
            print(f"[ERROR] 下载文件时出错: {str(e)}")
            try:
                self.send_error(500, "Download error")
            except:
                # 如果连接已断开，忽略发送错误响应的异常
                pass
    
    def send_file_list(self):
        """发送文件列表"""
        try:
            files = []
            if os.path.exists(self.upload_dir):
                for filename in os.listdir(self.upload_dir):
                    file_path = os.path.join(self.upload_dir, filename)
                    if os.path.isfile(file_path):
                        size = os.path.getsize(file_path)
                        size_str = self.format_file_size(size)
                        files.append({
                            'name': filename,
                            'size': size_str,
                            'bytes': size
                        })
            
            self.send_json_response(files)
            
        except Exception as e:
            self.send_json_response([])
    
    def send_json_response(self, data):
        """发送JSON响应"""
        response = json.dumps(data, ensure_ascii=False)
        self.send_response(200)
        self.send_header('Content-type', 'application/json; charset=utf-8')
        self.end_headers()
        self.wfile.write(response.encode('utf-8'))
    
    def format_file_size(self, size):
        """格式化文件大小"""
        for unit in ['B', 'KB', 'MB', 'GB']:
            if size < 1024:
                return f"{size:.1f} {unit}"
            size /= 1024
        return f"{size:.1f} TB"
    
    def log_message(self, format, *args):
        """重写日志方法，显示请求信息用于调试"""
        print(f"[HTTP] {format % args}")


class HttpServerPlugin(BasePlugin):
    """HTTP文件服务器插件"""
    
    def __init__(self):
        super().__init__()
        self.name = "httpserver"
        self.version = "1.0.0"
        self.description = "HTTP文件服务器，支持文件上传和下载"
        self.server = None
        self.server_thread = None
        self.upload_dir = "uploads"
        
    def execute(self, args):
        """执行HTTP服务器功能"""
        if not args:
            self.show_help()
            return True
            
        command = args[0].lower()
        
        if command == 'start':
            self.start_server(args[1:])
        elif command == 'stop':
            self.stop_server()
        elif command == 'status':
            self.show_status()
        elif command == 'help':
            self.show_help()
        else:
            print(f"未知命令: {command}")
            self.show_help()
            
        return True
    
    def start_server(self, args):
        """启动HTTP服务器"""
        if self.server is not None:
            print("服务器已在运行中")
            return
        
        # 解析参数：支持 IP 和端口
        host = '0.0.0.0'  # 默认绑定所有网络接口
        port = 8000       # 默认端口
        
        if len(args) == 1:
            # 只有一个参数，判断是IP还是端口
            arg = args[0]
            if arg.isdigit():
                # 纯数字，当作端口
                port = int(arg)
            else:
                # 包含点号，当作IP地址
                host = arg
        elif len(args) == 2:
            # 两个参数：IP 和 端口
            host = args[0]
            if args[1].isdigit():
                port = int(args[1])
            else:
                print("错误: 端口必须是数字")
                return
        elif len(args) > 2:
            print("错误: 参数过多")
            print("用法: httpserver start [IP] [端口]")
            return
        
        try:
            # 验证IP地址格式
            if host != '0.0.0.0' and host != 'localhost':
                import ipaddress
                try:
                    ipaddress.ip_address(host)
                except ValueError:
                    print(f"错误: 无效的IP地址格式: {host}")
                    return
            
            # 创建上传目录
            os.makedirs(self.upload_dir, exist_ok=True)
            
            # 创建服务器处理器
            def handler(*args, **kwargs):
                return FileServerHandler(*args, upload_dir=self.upload_dir, **kwargs)
            
            # 启动服务器
            self.server = HTTPServer((host, port), handler)
            
            # 在新线程中运行服务器
            self.server_thread = threading.Thread(target=self.server.serve_forever)
            self.server_thread.daemon = True
            self.server_thread.start()
            
            print(f"HTTP文件服务器已启动")
            print(f"绑定地址: {host}:{port}")
            
            # 显示访问地址
            if host == '0.0.0.0':
                print(f"本地访问: http://localhost:{port}")
                print(f"局域网访问: http://[本机IP]:{port}")
                # 尝试获取本机IP
                try:
                    import socket
                    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                    s.connect(("8.8.8.8", 80))
                    local_ip = s.getsockname()[0]
                    s.close()
                    print(f"建议局域网访问: http://{local_ip}:{port}")
                except:
                    pass
            else:
                print(f"访问地址: http://{host}:{port}")
            
            print(f"上传目录: {os.path.abspath(self.upload_dir)}")
            print("使用 'httpserver stop' 停止服务器")
            
        except OSError as e:
            if e.errno == 10048:  # 端口被占用
                print(f"端口 {port} 已被占用，请尝试其他端口")
            elif e.errno == 10049:  # 无法绑定到指定地址
                print(f"无法绑定到地址 {host}:{port}，请检查IP地址是否正确")
            else:
                print(f"启动服务器失败: {e}")
        except Exception as e:
            print(f"启动服务器时出错: {e}")
    
    def stop_server(self):
        """停止HTTP服务器"""
        if self.server is None:
            print("服务器未运行")
            return
        
        try:
            self.server.shutdown()
            self.server.server_close()
            self.server = None
            self.server_thread = None
            print("HTTP服务器已停止")
        except Exception as e:
            print(f"停止服务器时出错: {e}")
    
    def show_status(self):
        """显示服务器状态"""
        if self.server is None:
            print("服务器状态: 未运行")
        else:
            host, port = self.server.server_address
            print("服务器状态: 运行中")
            print(f"访问地址: http://{host}:{port}")
            print(f"上传目录: {os.path.abspath(self.upload_dir)}")
            
            # 显示文件统计
            if os.path.exists(self.upload_dir):
                files = [f for f in os.listdir(self.upload_dir) 
                        if os.path.isfile(os.path.join(self.upload_dir, f))]
                print(f"已上传文件数: {len(files)}")
    
    def show_help(self):
        """显示帮助信息"""
        print("\n=== HTTP文件服务器使用说明 ===")
        print("用法: httpserver <命令> [参数]")
        print("\n可用命令:")
        print("  start [IP] [端口]  - 启动HTTP服务器")
        print("  stop              - 停止HTTP服务器")
        print("  status            - 查看服务器状态")
        print("  help              - 显示此帮助信息")
        print("\n启动参数说明:")
        print("  IP地址: 服务器绑定的IP地址 (默认: 0.0.0.0 - 所有网络接口)")
        print("  端口:   服务器监听的端口号 (默认: 8000)")
        print("\n功能特性:")
        print("  • 支持拖拽文件上传")
        print("  • 支持多文件同时上传")
        print("  • 提供文件下载链接")
        print("  • 自动生成文件列表")
        print("  • 支持各种文件类型")
        print("  • 支持局域网访问")
        print("\n启动示例:")
        print("  httpserver start                    # 默认启动 (0.0.0.0:8000)")
        print("  httpserver start 9000               # 指定端口 (0.0.0.0:9000)")
        print("  httpserver start 192.168.1.100      # 指定IP (192.168.1.100:8000)")
        print("  httpserver start 192.168.1.100 9000 # 指定IP和端口")
        print("  httpserver start localhost 8080     # 仅本地访问")
        print("\n其他命令:")
        print("  httpserver status                   # 查看服务器状态")
        print("  httpserver stop                     # 停止服务器")
        print("\n注意事项:")
        print("  • 使用 0.0.0.0 可以让局域网内其他设备访问")
        print("  • 使用 localhost 或 127.0.0.1 仅允许本机访问")
        print("  • 确保防火墙允许指定端口的访问")
        
    def get_help(self):
        """获取插件帮助信息"""
        return f"{self.name}: {self.description}\n  用法: httpserver <start|stop|status|help> [IP] [端口]"